package com.hw.interceptor;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.hw.dagl.model.Sys_User;
import com.hw.dagl.model.Sys_User_Log;
import com.hw.dagl.service.SysUserLogService;
import com.hw.utils.IpUtil;

import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;

public class LogAspect {
	@Resource
	public SysUserLogService sysUserLogServiceImpl;
	
	private HttpServletRequest request=null;
	
	public void before(JoinPoint joinPoint){
		
	}
	/* public Object around(ProceedingJoinPoint point) throws Throwable {
	        System.out.println("@Around：执行目标方法之前...");
	        //访问目标方法的参数：
	        Object[] args = point.getArgs();
	        if (args != null && args.length > 0) {
	           // args[0] = "改变后的参数1";
	            System.out.println(args[0].getClass().getName());
	        }
	        //用改变后的参数执行目标方法
	        //Object returnValue = point.proceed(args);
	        System.out.println("@Around：执行目标方法之后...");
	        System.out.println("@Around：被织入的目标对象为：" + point.getTarget());
	        return "原返回值：" + "" + "，这是返回结果的后缀";
	    }*/
	
	public void after(JoinPoint joinPoint) throws Exception{
		request = getHttpServletRequest();
		if(request ==null){ return; }
		Sys_User user = (Sys_User) request.getSession().getAttribute("user");
		String targetName=joinPoint.getTarget().getClass().getName();
		String methodName=joinPoint.getSignature().getName();
		//System.out.println(methodName+"==============="+joinPoint.getTarget());
		Object[] arguments = joinPoint.getArgs();  
        Class targetClass = null;
        try {
            targetClass = Class.forName(targetName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }  
        Method[] methods = targetClass.getMethods();
        String operationName = "";
        String operationType = "";
        String Modelname = "";
        for (Method method : methods) {  
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();  
                if (clazzs!=null&&clazzs.length == arguments.length&&method.getAnnotation(SystemLog.class)!=null) {  
                    operationName = method.getAnnotation(SystemLog.class).operationName();
                    operationType = method.getAnnotation(SystemLog.class).operationType();
                    Modelname = method.getAnnotation(SystemLog.class).Modelname();
                    if (user != null && user.getYhdh() != null){
            			Sys_User_Log log = new Sys_User_Log();
            			log.setOptype(operationType);
            			log.setMethoddesc(operationName);
            			log.setModelname(Modelname);
            			log.setIp(IpUtil.getIpAddr(request));
            			log.setUrl(request.getRequestURI());
            			log.setYhdh(user.getYhdh());
            			log.setDateTime(new Date());
            			log.setDetailisnot("0");
            			if(method.getAnnotation(SystemLog.class).detailFlag()==true){
            				//System.out.println("参数列表："+Arrays.toString(arguments)+arguments[0].getClass().getDeclaredFields()[0]);
            				/*String classType = joinPoint.getTarget().getClass().getName();    
            		        Class<?> clazz = Class.forName(classType);    
            		        String clazzName = clazz.getName();    
            		        String methodName2 = joinPoint.getSignature().getName(); //获取方法名称 
            				//获取参数名称和值  
            		        Map<String,Object > nameAndArgs = this.getFieldsName(this.getClass(), clazzName, methodName2,arguments);  */ 
            				//接下来查找更新时候，对象变化的字段
            				
            				log.setDetailisnot("1"); //设置是否有详情字段，1代表有详情
            				Object obj = joinPoint.getThis();
            				Object targetObject = null;
            				Map<String,Object> targetMap = null;
            				if(method.getAnnotation(SystemLog.class).targetObject() != null && !"".equals(method.getAnnotation(SystemLog.class).targetObject())){
            					Method targetMethod = null;
            					try {
            						//System.out.println("obj.getClass()=="+obj.getClass());
            						targetMethod = obj.getClass().getMethod("get" + method.getAnnotation(SystemLog.class).targetObject());
            					} catch (Exception e) {
            						e.printStackTrace();
            					}
            					if(targetMethod == null){
            						//如果没有方法的话，就给个默认
            						targetMap = new HashMap<String,Object>();
            					}else{
            						targetObject = targetMethod.invoke(obj);
            						 String[] strs= new String[]{"xh","lsh","hphm","hpzl","syr","clsbdh","ywmc","clpp1","tpurl","ywlx","ywyy"};
            						 targetMap = getObjValue(targetObject,strs);
            						 for(Entry<String,Object> entiy : targetMap.entrySet()){
            							 if(entiy.getKey()=="xh"){log.setXh(entiy.getValue().toString());continue;}
            							 else if(entiy.getKey()=="lsh"){log.setLsh(entiy.getValue().toString());continue;}
            							 else if(entiy.getKey()=="hphm"){log.setHphm(entiy.getValue().toString());continue;}
            							 else if(entiy.getKey()=="hpzl"){log.setHpzl(entiy.getValue().toString());continue;}
            							 else if(entiy.getKey()=="syr"){log.setSyr(entiy.getValue().toString());continue;}
            							 else if(entiy.getKey()=="clsbdh"){log.setClsbdh(entiy.getValue().toString());continue;}
            							 else if(entiy.getKey()=="ywmc"){log.setYwmc(entiy.getValue().toString());continue;}
            							 else if(entiy.getKey()=="clpp1"){log.setClpp1(entiy.getValue().toString());continue;}
            							 else if(entiy.getKey()=="tpurl"){log.setTpurl(entiy.getValue().toString());continue;}
            							 else if(entiy.getKey()=="ywlx"){log.setYwlx(entiy.getValue().toString());continue;}
            							 else if(entiy.getKey()=="ywyy"){log.setYwyy(entiy.getValue().toString());}
            						 }
            					}
            				}
        
            			}
            			// 异步保存日志
            			new SaveLogThread(log).start();
            		}
                    break;
                }  
            }  
        }

	}
	/**
	   * 获取Object全部属性及对应属性值
	   * @param model
	   */
	  public void getObjValue(Object model) {
	    Class cls = model.getClass();
	    Field[] fields = cls.getDeclaredFields();
	    for (Field field : fields) {
	        char[] buffer = field.getName().toCharArray();
	        buffer[0] = Character.toUpperCase(buffer[0]);
	        String mothodName = "get" + new String(buffer);
	        try {
	          Method method = cls.getDeclaredMethod(mothodName);
	          Object resutl = method.invoke(model, null);
	          //System.out.println(field.getName() + ": " + resutl);
	        } catch (Exception e) {
	          e.printStackTrace();
	        }
	    }
	  }
	/**
	 * 获取指定Object部分属性及对应属性值,装入map中
	 * @param model
	 * @param fields
	 */
	  public Map<String, Object> getObjValue(Object model, String[] fields) {
		  	Map<String, Object> map = new HashMap<String, Object>();
		  	//System.out.println("model:"+model.toString());
		    Class cls = model.getClass();
		    for (String field : fields) {
		        char[] buffer = field.toCharArray();
		        buffer[0] = Character.toUpperCase(buffer[0]);
		        String mothodName = "get" + new String(buffer);
		        try {
		          Method method = cls.getDeclaredMethod(mothodName);
		          Object resutl = method.invoke(model, null);
		          map.put(field, resutl);
		         //System.out.println(field + ": " + resutl);
		        } catch (Exception e) {
		          e.printStackTrace();
		        }
		    }
		    return map;
		  }
	

	/**
	 * 保存日志线程
	 */
	public class SaveLogThread extends Thread{
		
		private Sys_User_Log log;
		
		public SaveLogThread(Sys_User_Log log){
			super(SaveLogThread.class.getSimpleName());
			this.log = log;
		}
		
		@Override
		public void run() {
			sysUserLogServiceImpl.insertSysUserLog(log);
		}
	}
	/**
	 * 获取request实例
	 * @return
	 */
    public HttpServletRequest getHttpServletRequest(){
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes)ra; 
        HttpServletRequest request = null;
        try{
        	request = sra.getRequest();
        } catch (Exception e){
        	return null;
        }
        return request;
    }
}
